package com.java.hohenheim.springplatform.web.handler;

import com.java.hohenheim.springplatform.data.web.BaseRespModel;
import com.java.hohenheim.springplatform.define.ResultCodes;
import com.java.hohenheim.springplatform.exception.PlatformException;
import com.java.hohenheim.springplatform.web.ResultPackWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.exceptions.PersistenceException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.beans.BeansException;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import java.io.IOException;
import java.sql.SQLException;
import java.util.List;

/**
 * @author Hohenheim
 * @date 2018/4/28
 * @description Controller 统一错误拦截器
 */
@ControllerAdvice(basePackages = {"com.java.hohenheim.springplatform.web.controller",
        						  "com.java.hohenheim.springplatform.web.service"})
@Slf4j
public class ControllerExceptionHandle {
    @ExceptionHandler(value = PlatformException.class)
    @ResponseBody
    public BaseRespModel apiReqException(PlatformException exception) {
        if(exception.isLogging()) {
            String logMsg = StringUtils.isEmpty(exception.getLogMsg()) ? exception.getMessage() : exception.getLogMsg();
            log.error("[SpringPlatform] API错误：" + logMsg, exception);
        }

        return ResultPackWrapper.reqFail(exception.getCode(), exception.getMessage());
    }

//    @ExceptionHandler(value = {IOException.class, SQLException.class})
    @ExceptionHandler(value = {IOException.class, PersistenceException.class, SQLException.class})
    @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public BaseRespModel apiReqException(Exception exception) {
        log.error("[SpringPlatform] IO/SQL错误：", exception);
        return ResultPackWrapper.reqFail(ResultCodes.COMMON_SYSTEM_ERROR);
    }

    @ExceptionHandler(value = {MethodArgumentNotValidException.class, BindException.class})
    @ResponseStatus(code= HttpStatus.BAD_REQUEST)
    @ResponseBody
    public BaseRespModel validException(Exception e) {
        BindingResult result;
        if(e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e;
            result = exception.getBindingResult();
        }
        else {
            BindException exception = (BindException) e;
            result = exception.getBindingResult();
        }

        List<FieldError> fieldErrors = result.getFieldErrors();
        StringBuilder builder = new StringBuilder();
        for (FieldError error : fieldErrors) {
            builder.append(error.getDefaultMessage()).append("|");
        }
        builder.deleteCharAt(builder.length() - 1);
        String errMsg = builder.toString();

        return ResultPackWrapper.reqFail(ResultCodes.COMMON_INVALID_PARAMS.getCode(), errMsg);
    }

    @ExceptionHandler(value = NullPointerException.class)
    @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public BaseRespModel nullPointerException(NullPointerException ex) {
        log.error("[SpringPlatform] 空指针异常：" + ex.getMessage(), ex);
        return ResultPackWrapper.reqFail(ResultCodes.COMMON_SYSTEM_ERROR);
    }

    @ExceptionHandler(value = BeansException.class)
    @ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
    @ResponseBody
    public BaseRespModel beansException(BeansException ex) {
        log.error("[SpringPlatform] 数据复制异常：" + ex.getMessage(), ex);
        return ResultPackWrapper.reqFail(ResultCodes.COMMON_SYSTEM_ERROR);
    }

    /**
     * 认证失败错误
     */
    @ExceptionHandler(value = UnauthorizedException.class)
    @ResponseStatus(code = HttpStatus.UNAUTHORIZED)
    @ResponseBody
    public BaseRespModel unauthorizedException(UnauthorizedException ex) {
        return ResultPackWrapper.reqFail(ResultCodes.UNAUTHORIZED);
    }
}